#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Swift混淆器
专门处理Swift代码的混淆
"""

import os
import re
from typing import Dict, List, Set, Tuple
from ..builtin_config_module.builtin_config import BuiltInConfig
from ..utils_module.logger import ObfuscationLogger

class SwiftObfuscator:
    """Swift混淆器"""
    
    def __init__(self, config: BuiltInConfig, logger: ObfuscationLogger):
        self.config = config
        self.logger = logger
        
        # Swift语法模式
        self.patterns = {
            'class': r'\bclass\s+(\w+)',
            'struct': r'\bstruct\s+(\w+)',
            'enum': r'\benum\s+(\w+)',
            'protocol': r'\bprotocol\s+(\w+)',
            'function': r'\bfunc\s+(\w+)',
            'property': r'\b(var|let)\s+(\w+)',
            'constant': r'\bstatic\s+(let|var)\s+(\w+)',
            'extension': r'\bextension\s+(\w+)'
        }
    
    def extract_symbols(self, file_path: str) -> List[str]:
        """提取Swift文件中的符号"""
        symbols = []
        
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # 提取各种类型的符号
            for symbol_type, pattern in self.patterns.items():
                matches = re.findall(pattern, content)
                for match in matches:
                    if isinstance(match, tuple):
                        symbol = match[1] if len(match) > 1 else match[0]
                    else:
                        symbol = match
                    
                    # 使用配置来判断是否可混淆
                    if self.config.is_symbol_safe_to_obfuscate(symbol, 'swift', '')[0]:
                        symbols.append(symbol)
            
            # 去重
            symbols = list(set(symbols))
            
        except Exception as e:
            self.logger.log_error(f"提取Swift符号失败: {file_path}, 错误: {str(e)}")
        
        return symbols
    
    def obfuscate_file(self, file_path: str, symbol_map: Dict[str, str]):
        """混淆Swift文件"""
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            original_content = content
            
            # 保护字符串和注释不被替换
            protected_regions = self._identify_protected_regions(content)
            # 添加保护delegate方法签名区域
            protected_regions.extend(self._identify_delegate_regions(content))
            
            # 按符号长度排序，优先替换长符号
            sorted_symbols = sorted(symbol_map.items(), key=lambda x: len(x[0]), reverse=True)
            
            for original, obfuscated in sorted_symbols:
                # 使用更智能的替换模式
                content = self._smart_replace(content, original, obfuscated, protected_regions)
            
            # 检查是否有变化
            if content != original_content:
                if not self.config.dry_run:
                    with open(file_path, 'w', encoding='utf-8') as f:
                        f.write(content)
                
                self.logger.log_file_processing(file_path, "已混淆")
            else:
                self.logger.log_file_processing(file_path, "无需混淆")
                
        except Exception as e:
            self.logger.log_error(f"混淆Swift文件失败: {file_path}, 错误: {str(e)}")
    
    def extract_class_symbols(self, content: str) -> List[str]:
        """提取类符号"""
        classes = []
        pattern = r'\bclass\s+(\w+)'
        matches = re.findall(pattern, content)
        for match in matches:
            if self.config.is_symbol_safe_to_obfuscate(match, 'swift'):
                classes.append(match)
        return classes
    
    def _identify_protected_regions(self, content: str) -> List[Tuple[int, int]]:
        """识别不应被混淆的区域（字符串、注释等）"""
        regions = []
        
        # 多行注释 /* ... */
        for match in re.finditer(r'/\*.*?\*/', content, re.DOTALL):
            regions.append((match.start(), match.end()))
        
        # 单行注释 //
        for match in re.finditer(r'//.*?$', content, re.MULTILINE):
            regions.append((match.start(), match.end()))
        
        # 字符串 "..." 和 """..."""
        for match in re.finditer(r'""".*?"""|"(?:[^"\\]|\\.)*"', content, re.DOTALL):
            regions.append((match.start(), match.end()))
        
        # 字符串 '...'
        for match in re.finditer(r"'(?:[^'\\]|\\.)*'", content):
            regions.append((match.start(), match.end()))
            
        return sorted(regions)
    
    def _identify_delegate_regions(self, content: str) -> List[Tuple[int, int]]:
        """识别delegate方法签名区域"""
        regions = []
        
        # 匹配tableView, collectionView等delegate方法
        delegate_patterns = [
            r'func\s+\w+\([^)]*tableView\s*:\s*UITableView[^)]*\)',
            r'func\s+\w+\([^)]*collectionView\s*:\s*UICollectionView[^)]*\)',
            r'func\s+\w+\([^)]*scrollView\s*:\s*UIScrollView[^)]*\)',
            r'func\s+\w+\([^)]*textField\s*:\s*UITextField[^)]*\)',
            r'func\s+\w+\([^)]*textView\s*:\s*UITextView[^)]*\)',
            r'func\s+\w+\([^)]*picker\s*:\s*UIPicker[^)]*\)',
            r'func\s+\w+\([^)]*searchBar\s*:\s*UISearchBar[^)]*\)',
            # 保护override func整体
            r'override\s+func\s+\w+',
            # 保护@objc方法
            r'@objc\s+(?:func\s+)?\w+'
        ]
        
        for pattern in delegate_patterns:
            for match in re.finditer(pattern, content):
                regions.append((match.start(), match.end()))
        
        return sorted(regions)
    
    def _smart_replace(self, content: str, original: str, obfuscated: str, protected_regions: List[Tuple[int, int]]) -> str:
        """智能替换，处理特殊情况，确保所有引用都被替换"""
        result = []
        last_pos = 0
        
        # 构建更精确的替换模式 - 使用词边界
        pattern = r'\b' + re.escape(original) + r'\b'
        
        for match in re.finditer(pattern, content):
            # 检查是否在保护区域内（字符串、注释等）
            in_protected = False
            for start, end in protected_regions:
                if start <= match.start() < end:
                    in_protected = True
                    break
            
            if in_protected:
                # 在保护区域内，不替换
                result.append(content[last_pos:match.end()])
                last_pos = match.end()
                continue
            
            # 获取上下文
            before_text = content[max(0, match.start()-30):match.start()]
            after_text = content[match.end():min(len(content), match.end()+30)]
            
            # 特殊情况处理
            should_skip = False
            
            # 1. 检查是否是系统保留符号（通过配置判断）
            if not self.config.is_symbol_safe_to_obfuscate(original, 'swift'):
                should_skip = True
            
            # 2. 不替换 override 后面的方法名
            elif 'override' in before_text and 'func' in before_text:
                # 检查是否是紧跟在 override func 后面的方法名
                override_pattern = r'override\s+func\s*$'
                if re.search(override_pattern, before_text):
                    should_skip = True
            
            # 3. 不替换 @IBAction, @IBOutlet, @objc 的声明（但替换引用）
            elif re.search(r'@(IBAction|IBOutlet|objc)\s+\w*\s*$', before_text):
                # 只在声明时跳过（有var/let/func关键字）
                if re.search(r'\b(var|let|func)\s+$', before_text[-50:]):
                    should_skip = True
            
            if should_skip:
                result.append(content[last_pos:match.end()])
                last_pos = match.end()
            else:
                # 执行替换 - 这将替换所有引用，包括 self.property 和直接引用
                result.append(content[last_pos:match.start()])
                result.append(obfuscated)
                last_pos = match.end()
        
        # 添加剩余内容
        result.append(content[last_pos:])
        return ''.join(result)
    
    def _safe_replace(self, content: str, pattern: str, replacement: str, protected_regions: List[Tuple[int, int]]) -> str:
        """安全替换，跳过保护区域（保留以兼容）"""
        result = []
        last_pos = 0
        
        for match in re.finditer(pattern, content):
            # 检查是否在保护区域内
            in_protected = False
            for start, end in protected_regions:
                if start <= match.start() < end:
                    in_protected = True
                    break
            
            if not in_protected:
                # 添加匹配前的内容
                result.append(content[last_pos:match.start()])
                # 添加替换内容
                result.append(replacement)
                last_pos = match.end()
        
        # 添加剩余内容
        result.append(content[last_pos:])
        return ''.join(result)
    
    def extract_function_symbols(self, content: str) -> List[str]:
        """提取函数符号"""
        functions = []
        pattern = r'\bfunc\s+(\w+)'
        matches = re.findall(pattern, content)
        for match in matches:
            if self.config.is_symbol_safe_to_obfuscate(match, 'swift'):
                functions.append(match)
        return functions
    
    def extract_property_symbols(self, content: str) -> List[str]:
        """提取属性符号"""
        properties = []
        pattern = r'\b(var|let)\s+(\w+)'
        matches = re.findall(pattern, content)
        for match in matches:
            if self.config.is_symbol_safe_to_obfuscate(match[1], 'swift'):
                properties.append(match[1])
        return properties
